import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt

class MyLogisticRegression():
    def __init__(self):
        self.coef = []
        self.intercept = []
        self.class_num = 0
        self.feature_num = 0
        return

    def logistic_func(z):
        return 1/(1+np.exp(-z))

    def P1(w_aug, X_aug):
        z=np.matmul(X_aug, w_aug)
        return MyLogisticRegression.logistic_func(z)

    def gradient(w_aug, X_aug, y):
        p1 = MyLogisticRegression.P1(w_aug, X_aug)
        return np.matmul(X_aug.T, p1-y)

    def logistic_regress(X, y):
        X = np.mat(X)
        y = np.mat(y).T
        X_aug = np.append(X, np.ones([X.shape[0], 1]), axis=1)
        w_aug = np.zeros([X.shape[1]+1, 1])
        n = 0.001
        er = 0.01
        grad = MyLogisticRegression.gradient(w_aug, X_aug, y)
        while sum(np.array(grad)**2) > er:
            w_aug = w_aug-n*grad
            grad = MyLogisticRegression.gradient(w_aug, X_aug, y)
        w_aug = w_aug.T.tolist()[0]
        return w_aug[0:-1], w_aug[-1]

    def fit(self, data, target, class_num):
        self.class_num = class_num
        self.feature_num = data.shape[1]
        if self.class_num == 2:
            self.coef, self.intercept = MyLogisticRegression.logistic_regress(data, target==1)
        else:
            for idx in range(0,class_num):
                w, b = MyLogisticRegression.logistic_regress(data, target==idx)
                list.append(self.coef, w)
                list.append(self.intercept, b)
        return

    def predict(self, data):
        coef_aug = np.append(np.mat(self.coef), np.mat(self.intercept).T, axis=1)
        data_aug = np.append(np.mat(data), np.ones([len(data), 1]), axis=1)
        Y = np.matmul(data_aug, coef_aug.T)
        if self.class_num == 2:
            label = (Y.T >= 0).tolist()[0]
        else:
            label = np.argmax(Y.tolist(), axis=1).tolist()
        return label

    def score(self, data, target):
        score = sum(self.predict(data) == target)/len(target)
        return score;

#西瓜数据集
watermelon = np.loadtxt('./logistic_regression/watermelon.txt', skiprows=0, delimiter=' ')
wat_data = watermelon[:,:-1]
wat_target = watermelon[:,-1]
wat_regr = MyLogisticRegression()
wat_regr.fit(wat_data, wat_target, 2)
print('Score: %.2f'%wat_regr.score(wat_data,wat_target))
plt.title('watermelon_3a')
plt.xlabel('density')
plt.ylabel('ratio sugar')
plt.scatter(wat_data[wat_target==1,0],wat_data[wat_target==1,1], marker ='+', color = 'r', s = 40,label= 'good')
plt.scatter(wat_data[wat_target==0,0],wat_data[wat_target == 0,1], marker ='*',color = 'b',s = 40,label = 'bad')
plt.legend(loc= 'upper right')
x=np.linspace(0,1,2)
y=-(wat_regr.coef[0]*x+wat_regr.intercept)/wat_regr.coef[1]
plt.plot(x,y)
plt.show()

#鸢尾花数据集
'''
iris = datasets.load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, stratify=iris.target)
iris_regr = MyLogisticRegression()
iris_regr.fit(X_train, y_train, 3)
print('Coefficent: %s, intercept: %s'%(iris_regr.coef,iris_regr.intercept))
print('Score: %.2f'%iris_regr.score(X_test, y_test))
print(classification_report(y_test,iris_regr.predict(X_test)))
'''